#include "config.h"


#define SEM_SIZE (20)

int master_fd = -1;
int vistor_fd = -1;

// 信号量--判断群聊人数
sem_t sem;
// 服务端文件描述符
int svr_fd;
// 存储群友，多一个是为了当群人满时，空一个出来接发信息
int cli_fd[SEM_SIZE + 1] = {};

client_t clients[SEM_SIZE] = {};

char buffer[BUFFER_SIZE] = {};
/**
 * 发送给指定的用户
 * char *buf 发送的消息
 * int fd 发给谁
 */
void* send_one(message_t* buf, int fd)
{
    printf("send to %d : %s\n", fd, buf->recv_name);
    // printf("send to %d\n", fd);
    write(fd, buf, sizeof(message_t));
}

// 服务端接收函数
void* handleRequest(void* arg)
{
    int       fd   = *(int*)arg;
    message_t mesg = {};

    // 获取昵称
    // recv(fd, buffer, sizeof(buffer), 0);
    // memcpy(&mesg, buffer, sizeof(buffer));

    clients[fd].sockfd = fd;
    // memset(clients[fd].user_name, 0, sizeof(clients[fd].user_name));
    // strncpy(clients[fd].user_name, mesg.send_name, strlen(mesg.send_name) + 1);

    // printf("clients[fd].name = %s\n", clients[fd].user_name);
    printf("存放clients[fd].client_fd = %d\n", clients[fd].sockfd);

    for (;;) {
        // 接收信息,无信息时将阻塞
        int recv_size = read(fd, &buffer, sizeof(buffer));
        memcpy(&mesg, buffer, sizeof(buffer));

        if (recv_size <= 0 || mesg.cli_msg == CLIENT_MSG_EXIT_ROOM) {
            if (fd == master_fd) {
                mesg.srv_msg = SERVER_MSG_CLOSE_CONNECT;
                memset(buffer, 0, sizeof(buffer));
                memcpy(buffer, &mesg, sizeof(buffer));
                write(master_fd, buffer, sizeof(buffer));
                master_fd = -1;
                if (vistor_fd != -1) {
                    mesg.srv_msg = SERVER_MSG_OTHER_EXIT_ROOM;
                    memset(buffer, 0, sizeof(buffer));
                    memcpy(buffer, &mesg, sizeof(buffer));
                    write(vistor_fd, buffer, sizeof(buffer));
                }
            }
            else if (fd == vistor_fd) {
                          mesg.srv_msg = SERVER_MSG_CLOSE_CONNECT;
                memset(buffer, 0, sizeof(buffer));
                memcpy(buffer, &mesg, sizeof(buffer));
                write(vistor_fd, buffer, sizeof(buffer));
                vistor_fd = -1;
                if (master_fd != -1) {
                    mesg.srv_msg = SERVER_MSG_OTHER_EXIT_ROOM;
                    memset(buffer, 0, sizeof(buffer));
                    memcpy(buffer, &mesg, sizeof(buffer));
                    write(master_fd, buffer, sizeof(buffer));
                }
            }

            int index = 0;
            // 找到要退出的那个人，并将其置为-1
            for (; index < SEM_SIZE; index++) {
                if (cli_fd[index] == fd) {
                    cli_fd[index] = -1;
                    break;
                }
            }
            clients[fd].sockfd = -1;
            // 群友退出，信号量+1
            int n;
            sem_post(&sem);
            sem_getvalue(&sem, &n);

            printf("[system] %s 离开群聊,群聊还剩%d人\n", clients[fd].user_name, SEM_SIZE - n);
            close(fd);
            pthread_exit(NULL);
        }

        printf("mesg.cli_msg=%d\n", mesg.cli_msg);
        printf("mesg.srv_msg=%d\n", mesg.srv_msg);
        switch (mesg.cli_msg) {
        case CLIENT_MSG_CREATE_ROOM:
            if (master_fd == -1) {
                master_fd    = fd;
                mesg.srv_msg = SERVER_MSG_OPERA_SUCCESS;
                mesg.color   = 1;
                memset(buffer, 0, sizeof(buffer));
                memcpy(buffer, &mesg, sizeof(buffer));
                write(master_fd, buffer, sizeof(buffer));
            }
            else {
                mesg.srv_msg = SERVER_MSG_OPERA_FAILED;
                memset(buffer, 0, sizeof(buffer));
                memcpy(buffer, &mesg, sizeof(buffer));
                write(fd, buffer, sizeof(buffer));
            }
            break;

        case CLIENT_MSG_JOIN_ROOM:
            if (vistor_fd == -1) {
                vistor_fd    = fd;
                mesg.srv_msg = SERVER_MSG_OPERA_SUCCESS;
                mesg.color   = 2;
                memset(buffer, 0, sizeof(buffer));
                memcpy(buffer, &mesg, sizeof(buffer));
                write(vistor_fd, buffer, sizeof(buffer));
            }
            else {
                mesg.srv_msg = SERVER_MSG_OPERA_FAILED;
                memset(buffer, 0, sizeof(buffer));
                memcpy(buffer, &mesg, sizeof(buffer));
                write(fd, buffer, sizeof(buffer));
            }
            break;

        case CLIENT_MSG_EXIT_ROOM:
            break;

        case CLIENT_MSG_AGREE:
            if (mesg.srv_msg == SERVER_MSG_OTHER_RESTART_GAME) {
                if (fd == master_fd) {
                    mesg.cli_msg = CLIENT_MSG_RESTART_GAME;
                    mesg.srv_msg = SERVER_MSG_OTHER_AGREE;
                    memset(buffer, 0, sizeof(buffer));
                    memcpy(buffer, &mesg, sizeof(buffer));
                    write(vistor_fd, buffer, sizeof(buffer));
                }
                else {
                    mesg.cli_msg = CLIENT_MSG_RESTART_GAME;
                    mesg.srv_msg = SERVER_MSG_OTHER_AGREE;
                    memset(buffer, 0, sizeof(buffer));
                    memcpy(buffer, &mesg, sizeof(buffer));
                    write(master_fd, buffer, sizeof(buffer));
                }
            }

            break;
        case CLIENT_MSG_REFUSED:
            if (mesg.srv_msg == SERVER_MSG_OTHER_RESTART_GAME) {
                if (fd == master_fd) {
                    mesg.cli_msg = CLIENT_MSG_RESTART_GAME;
                    mesg.srv_msg = SERVER_MSG_OTHER_REFUSED;
                    memset(buffer, 0, sizeof(buffer));
                    memcpy(buffer, &mesg, sizeof(buffer));
                    write(vistor_fd, buffer, sizeof(buffer));
                }
                else {
                    mesg.cli_msg = CLIENT_MSG_RESTART_GAME;
                    mesg.srv_msg = SERVER_MSG_OTHER_REFUSED;
                    memset(buffer, 0, sizeof(buffer));
                    memcpy(buffer, &mesg, sizeof(buffer));
                    write(master_fd, buffer, sizeof(buffer));
                }
            }
            break;
        case CLIENT_MSG_MOVE_CHESS:
            if (master_fd != -1 && vistor_fd != -1) {
                if (fd == master_fd) {
                    mesg.srv_msg = SERVER_MSG_OPERA_SUCCESS;
                    memset(buffer, 0, sizeof(buffer));
                    memcpy(buffer, &mesg, sizeof(buffer));
                    write(master_fd, buffer, sizeof(buffer));

                    mesg.cli_msg = CLIENT_NONE;
                    mesg.srv_msg = SERVER_MSG_OTHER_MOVE_CHESS;
                    memset(buffer, 0, sizeof(buffer));
                    memcpy(buffer, &mesg, sizeof(buffer));
                    write(vistor_fd, buffer, sizeof(buffer));
                }
                else if(fd == vistor_fd){
                    mesg.srv_msg = SERVER_MSG_OPERA_SUCCESS;
                    memset(buffer, 0, sizeof(buffer));
                    memcpy(buffer, &mesg, sizeof(buffer));
                    write(vistor_fd, buffer, sizeof(buffer));

                    mesg.cli_msg = CLIENT_NONE;
                    mesg.srv_msg = SERVER_MSG_OTHER_MOVE_CHESS;
                    memset(buffer, 0, sizeof(buffer));
                    memcpy(buffer, &mesg, sizeof(buffer));
                    write(master_fd, buffer, sizeof(buffer));
                }
            }
            else {
                // mesg.srv_msg = SERVER_MSG_OPERA_SUCCESS;
                mesg.srv_msg = SERVER_MSG_OPERA_FAILED;
                memset(buffer, 0, sizeof(buffer));
                memcpy(buffer, &mesg, sizeof(buffer));
                write(fd, buffer, sizeof(buffer));
            }


            break;
        case CLIENT_MSG_RESTART_GAME:
            if (fd == master_fd) {
                mesg.cli_msg = CLIENT_NONE;
                mesg.srv_msg = SERVER_MSG_OTHER_RESTART_GAME;
                memset(buffer, 0, sizeof(buffer));
                memcpy(buffer, &mesg, sizeof(buffer));
                write(vistor_fd, buffer, sizeof(buffer));
            }
            else {
                mesg.cli_msg = CLIENT_NONE;
                mesg.srv_msg = SERVER_MSG_OTHER_RESTART_GAME;
                memset(buffer, 0, sizeof(buffer));
                memcpy(buffer, &mesg, sizeof(buffer));
                write(master_fd, buffer, sizeof(buffer));
            }
            break;



        default:
            break;
        }
    }
}



/**
 * quit
 */
void sigint(int signum)
{
    close(svr_fd);
    sem_destroy(&sem);
    printf("[system]服务器关闭\n");
    _exit(0);
}

int main()
{
    signal(SIGINT, sigint);

    // 初始化信号量，上限SEM_SIZE人
    sem_init(&sem, 0, SEM_SIZE);

    // 创建socket对象
    printf("[system]创建socket对象...\n");
    svr_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (0 > svr_fd) {
        perror("socket");
        return -1;
    }

    // 端口复用函数：解决端口号被系统占用的情况
    int on = 1;
    int gg = setsockopt(svr_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
    if (gg == -1) {
        perror("setsockopt");
        return -1;
    }

    // 准备通信地址(自己)
    printf("[system]准备通信地址...\n");
    struct sockaddr_in addr = {};
    addr.sin_family         = AF_INET;
    addr.sin_port           = htons(PORT);
    addr.sin_addr.s_addr    = htonl(INADDR_ANY);
    socklen_t addrlen       = sizeof(addr);

    // 绑定socket对象与地址
    printf("[system]绑定socket对象与地址...\n");
    if (bind(svr_fd, (struct sockaddr*)&addr, addrlen)) {
        perror("bind");
        return -1;
    }

    // 设置监听和排除数量
    printf("[system]设置监听");
    if (listen(svr_fd, 10)) {
        perror("listen");
        return -1;
    }

    printf("[system]等待客户端链接...\n");
    // 将初始值置全为-1，表示该聊天位置没有人占领
    memset(cli_fd, -1, sizeof(cli_fd));

    for (;;) {
        int sem_num;
        sem_getvalue(&sem, &sem_num);

        // 找到没有人占领的聊天位
        int index = 0;
        while (cli_fd[index] != -1)
            index++;
        cli_fd[index] = accept(svr_fd, (struct sockaddr*)&addr, &addrlen);

        if (cli_fd[index] < 0) {
            perror("accept");
            return -1;
        }

        if (sem_num <= 0) {
            printf("[system]人数已满，%d号客户端链接失败\n", cli_fd[index]);

            message_t mesg = {};
            mesg.srv_msg   = SERVER_MSG_OPERA_FAILED;
            write(cli_fd[index], &mesg, sizeof(message_t));
            close(cli_fd[index]);
            cli_fd[index] = -1;
        }
        else {
            sem_trywait(&sem);
            sem_getvalue(&sem, &sem_num);
            printf("[system]%d号客户端链接成功,当前上线人数%d人\n",
                   cli_fd[index],
                   SEM_SIZE - sem_num);

            message_t mesg = {};
            mesg.srv_msg   = SERVER_MSG_OPERA_SUCCESS;
            write(cli_fd[index], &mesg, sizeof(message_t));

            // 创建线程客户端
            pthread_t tid;
            pthread_create(&tid, NULL, handleRequest, &cli_fd[index]);
        }
    }
}
